package com.lauor.smpdb;

import com.lauor.smpdb.util.SmpUtil;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.concurrent.TimeUnit;

/**
 * @function:连接池配置类
 */
public class SmpConfig {
    private final String DEFAULT_DRIVER_CLASS = "com.mysql.cj.jdbc.Driver";
    private final byte DEFAULT_MIN_IDLE = 4;
    private final short DEFAULT_MAX_ACTIVE = 40;
    private final long DEFAULT_KEEPALIVE_TIME_MILL = TimeUnit.MINUTES.toMillis(30);//30分钟
    private final long DEFAULT_MAX_WAIT_TIME_MILL = TimeUnit.SECONDS.toMillis(30);//30秒
    private final long DEFAULT_VALIDATION_TIME_OUT_MILL = TimeUnit.SECONDS.toMillis(5);
    //最大数据库连接数限制
    private final short MAX_ACTIVE_LIMIT = 16_000;

    private String name;
    private String driverClassName = DEFAULT_DRIVER_CLASS;//驱动
    private String url;
    private String username;
    private String password;
    //最小连接数,默认4
    private int minIdle = DEFAULT_MIN_IDLE;
    //最大连接数，默认40
    private int maxActive = DEFAULT_MAX_ACTIVE;
    //数据库连接有效期检查间隔时间ms,默认30分钟
    private long keepAliveTimeMillis = DEFAULT_KEEPALIVE_TIME_MILL;
    //获取数据库连接最大等待时间ms,默认30s,最小1s
    private long maxWaitMillis = DEFAULT_MAX_WAIT_TIME_MILL;
    //数据连接合法性校验超时时间,默认5s
    private long validationTimeoutMillis = DEFAULT_VALIDATION_TIME_OUT_MILL;
    //配置间隔多久进行一次检测，检测需要关闭的空闲连接，默认5秒，单位毫秒
    private long timeBetweenEvictionRunsMillis = 5000;

    public SmpConfig() {}

    public void copyStateTo(SmpConfig other) {
        for (Field field : SmpConfig.class.getDeclaredFields()) {
            if (!Modifier.isFinal(field.getModifiers())) {
                field.setAccessible(true);
                try {
                    field.set(other, field.get(this));
                }
                catch (Exception e) {
                    throw new RuntimeException("Failed to copy SmpConfig state: " + e.getMessage(), e);
                }
            }
        }
    }

    //配置合法性校验
    protected void validate(){
        //检验必填项
        if ( SmpUtil.isEmpty(this.url) ){
            throw new IllegalArgumentException("url cannot be empty");
        }
        if ( SmpUtil.isEmpty(this.username) ){
            throw new IllegalArgumentException("username cannot be empty");
        }
        if ( SmpUtil.isEmpty(this.password) ){
            throw new IllegalArgumentException("password cannot be empty");
        }
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getDriverClassName() {
        return driverClassName;
    }

    public void setDriverClassName(String driverClassName) {
        if ( SmpUtil.isEmpty(this.driverClassName) ){
            this.driverClassName = DEFAULT_DRIVER_CLASS;
            return;
        }
        this.driverClassName = driverClassName;
    }

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public int getMinIdle() {
        return minIdle;
    }

    public void setMinIdle(int minIdle) {
        if (this.minIdle < 1 || this.minIdle > MAX_ACTIVE_LIMIT){
            if (this.minIdle > this.maxActive){
                this.minIdle = this.maxActive;
            } else {
                this.minIdle = DEFAULT_MIN_IDLE;
            }
            return;
        }
        this.minIdle = minIdle;
    }

    public int getMaxActive() {
        return maxActive;
    }

    public void setMaxActive(int maxActive) {
        if (this.maxActive < 1 || this.maxActive > MAX_ACTIVE_LIMIT){
            this.maxActive = DEFAULT_MAX_ACTIVE;
            return;
        }
        this.maxActive = maxActive;
    }

    public long getKeepAliveTimeMillis() {
        return keepAliveTimeMillis;
    }

    public void setKeepaliveTimeMillis(long keepaliveTimeInMill) {
        if (this.keepAliveTimeMillis < 1000){
            this.keepAliveTimeMillis = DEFAULT_KEEPALIVE_TIME_MILL;
            return;
        }
        this.keepAliveTimeMillis = keepaliveTimeInMill;
    }

    public long getMaxWaitMillis() {
        return maxWaitMillis;
    }

    public void setMaxWaitMillis(long maxWaitMillis) {
        if (this.maxWaitMillis < 1000){
            this.maxWaitMillis = DEFAULT_MAX_WAIT_TIME_MILL;
            return;
        }
        this.maxWaitMillis = maxWaitMillis;
    }

    public long getValidationTimeoutMillis() {
        return validationTimeoutMillis;
    }

    public void setValidationTimeoutMillis(long validationTimeoutMillis) {
        if (this.validationTimeoutMillis < 1000){
            this.validationTimeoutMillis = DEFAULT_VALIDATION_TIME_OUT_MILL;
            return;
        }
        this.validationTimeoutMillis = validationTimeoutMillis;
    }

    public long getTimeBetweenEvictionRunsMillis() {
        return timeBetweenEvictionRunsMillis;
    }

    public void setTimeBetweenEvictionRunsMillis(long timeBetweenEvictionRunsMillis) {
        if (timeBetweenEvictionRunsMillis >= 1000){
            this.timeBetweenEvictionRunsMillis = timeBetweenEvictionRunsMillis;
        }
    }
}
